﻿// 使用必要的命名空间
using Microsoft.Win32;
using System;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows;
using System.Windows.Controls;

// 灵溪工具箱命名空间
namespace 灵溪工具箱
{
    // DllInject 窗口类
    public partial class DllInject : Window
    {
        // 选中的DLL文件路径
        private string selectedDllPath = string.Empty;

        // 构造函数
        public DllInject()
        {
            InitializeComponent();
            LoadProcesses();
            InitializeDllModules();
        }

        // 加载系统中的进程
        private void LoadProcesses()
        {
            try
            {
                var processes = Process.GetProcesses().OrderBy(p => p.ProcessName);
                foreach (var process in processes)
                {
                    ProcessComboBox.Items.Add(new ComboBoxItem
                    {
                        Content = $"{process.ProcessName} ({process.Id})",
                        Tag = process.Id
                    });
                }
            }
            catch (Exception ex)
            {
                Log($"加载进程时出错: {ex.Message}");
            }
        }

        // 初始化DLL模块下拉框
        private void InitializeDllModules()
        {
            DllModuleComboBox.SelectedIndex = 0; // 默认选择 kernel32.dll
        }

        // 进程选择框选择更改事件处理
        private void ProcessComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if (ProcessComboBox.SelectedItem is ComboBoxItem selectedItem && selectedItem.Tag is int pid)
            {
                PidTextBox.Text = pid.ToString();
            }
        }

        // 打开文件按钮点击事件处理
        private void OpenFile_Click(object sender, RoutedEventArgs e)
        {
            OpenFileDialog openFileDialog = new OpenFileDialog
            {
                Filter = "DLL Files (*.dll)|*.dll|All Files (*.*)|*.*",
                Title = "选择要注入的DLL文件"
            };

            if (openFileDialog.ShowDialog() == true)
            {
                selectedDllPath = openFileDialog.FileName;
                Log($"选择了DLL文件: {selectedDllPath}");
            }
        }

        // 运行注入按钮点击事件处理
        private void RunInjection_Click(object sender, RoutedEventArgs e)
        {
            if (string.IsNullOrEmpty(selectedDllPath))
            {
                MessageBox.Show("请选择要注入的DLL文件", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
                return;
            }

            if (!int.TryParse(PidTextBox.Text, out int pid) || pid <= 0)
            {
                MessageBox.Show("请输入有效的PID", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
                return;
            }

            if (DllModuleComboBox.SelectedItem is ComboBoxItem selectedItem)
            {
                string moduleName = selectedItem.Content.ToString();
                try
                {
                    bool success = false;
                    switch (moduleName)
                    {
                        case "kernel32.dll":
                            success = InjectDLL(pid, selectedDllPath);
                            break;
                        case "user32.dll":
                            success = InjectDLL(pid, selectedDllPath);
                            break;
                        case "advapi32.dll":
                            success = InjectDLL(pid, selectedDllPath);
                            break;
                        case "gdi32.dll":
                            success = InjectDLL(pid, selectedDllPath);
                            break;
                        default:
                            Log($"不支持的DLL模块: {moduleName}");
                            return;
                    }

                    if (success)
                    {
                        Log($"DLL注入成功: {selectedDllPath} 到 PID {pid}");
                        MessageBox.Show("DLL注入成功！", "成功", MessageBoxButton.OK, MessageBoxImage.Information);
                    }
                    else
                    {
                        Log($"DLL注入失败: {selectedDllPath} 到 PID {pid}");
                        MessageBox.Show("DLL注入失败，请检查日志信息。", "失败", MessageBoxButton.OK, MessageBoxImage.Error);
                    }
                }
                catch (Exception ex)
                {
                    Log($"运行注入时出错: {ex.Message}");
                    MessageBox.Show($"运行注入时出错: {ex.Message}", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
                }
            }
        }

        // 导入Windows API函数
        [DllImport("kernel32.dll")]
        private static extern IntPtr OpenProcess(uint processAccess, bool bInheritHandle, int processId);

        [DllImport("kernel32.dll", SetLastError = true)]
        private static extern IntPtr GetProcAddress(IntPtr hModule, string procName);

        [DllImport("kernel32.dll", SetLastError = true)]
        private static extern IntPtr VirtualAllocEx(IntPtr hProcess, IntPtr lpAddress, uint dwSize, uint flAllocationType, uint flProtect);

        [DllImport("kernel32.dll", SetLastError = true)]
        private static extern bool WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, byte[] lpBuffer, uint nSize, out UIntPtr lpNumberOfBytesWritten);

        [DllImport("kernel32.dll")]
        private static extern IntPtr CreateRemoteThread(IntPtr hProcess, IntPtr lpThreadAttributes, uint dwStackSize, IntPtr lpStartAddress, IntPtr lpParameter, uint dwCreationFlags, out IntPtr lpThreadId);

        [DllImport("kernel32.dll")]
        private static extern bool CloseHandle(IntPtr hObject);

        [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
        private static extern IntPtr GetModuleHandle(string lpModuleName);

        // 定义Windows API常量
        private const uint PROCESS_CREATE_THREAD = 0x0002;
        private const uint PROCESS_QUERY_INFORMATION = 0x0400;
        private const uint PROCESS_VM_OPERATION = 0x0008;
        private const uint PROCESS_VM_WRITE = 0x0020;
        private const uint PROCESS_VM_READ = 0x0010;

        private const uint MEM_COMMIT = 0x00001000;
        private const uint MEM_RESERVE = 0x00002000;
        private const uint PAGE_READWRITE = 4;

        // 注入DLL到指定进程
        private bool InjectDLL(int processId, string dllPath)
        {
            IntPtr hProcess = OpenProcess(PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION | PROCESS_VM_OPERATION |
                                         PROCESS_VM_WRITE | PROCESS_VM_READ, false, processId);
            if (hProcess == IntPtr.Zero)
            {
                Log($"无法打开进程ID {processId}: {Marshal.GetLastWin32Error()}");
                return false;
            }

            IntPtr loadLibraryAddr = GetProcAddress(GetModuleHandle("kernel32.dll"), "LoadLibraryW");
            if (loadLibraryAddr == IntPtr.Zero)
            {
                Log($"无法获取 LoadLibraryW 的地址: {Marshal.GetLastWin32Error()}");
                CloseHandle(hProcess);
                return false;
            }

            IntPtr allocMemAddress = VirtualAllocEx(hProcess, IntPtr.Zero, (uint)((dllPath.Length + 1) * Marshal.SizeOf(typeof(char))),
                                                    MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
            if (allocMemAddress == IntPtr.Zero)
            {
                Log($"内存分配失败: {Marshal.GetLastWin32Error()}");
                CloseHandle(hProcess);
                return false;
            }

            byte[] bytes = Encoding.Unicode.GetBytes(dllPath);
            UIntPtr bytesWritten;
            if (!WriteProcessMemory(hProcess, allocMemAddress, bytes, (uint)bytes.Length, out bytesWritten))
            {
                Log($"写入内存失败: {Marshal.GetLastWin32Error()}");
                CloseHandle(hProcess);
                return false;
            }

            IntPtr threadId;
            IntPtr remoteThread = CreateRemoteThread(hProcess, IntPtr.Zero, 0, loadLibraryAddr,
                                                   allocMemAddress, 0, out threadId);
            if (remoteThread == IntPtr.Zero)
            {
                Log($"创建远程线程失败: {Marshal.GetLastWin32Error()}");
                CloseHandle(hProcess);
                return false;
            }

            WaitForSingleObject(remoteThread, -1); // 等待线程结束
            CloseHandle(remoteThread);
            CloseHandle(hProcess);
            return true;
        }

        [DllImport("kernel32.dll", SetLastError = true)]
        private static extern uint WaitForSingleObject(IntPtr hHandle, int dwMilliseconds);

        // 记录日志信息
        private void Log(string message)
        {
            Dispatcher.Invoke(() =>
            {
                LogListBox.Items.Insert(0, $"[{DateTime.Now:HH:mm:ss}] {message}");
            });
        }
    }
}